package site.yunnong.atvris.portal.service.impl;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import site.yunnong.atvris.common.api.ResultCodeEnum;
import site.yunnong.atvris.common.dto.UserUpdateParam;
import site.yunnong.atvris.common.enumeration.UserEducationEnum;
import site.yunnong.atvris.common.exception.YunnongBusinessException;
import site.yunnong.atvris.dao.domain.*;
import site.yunnong.atvris.dao.mapper.*;
import site.yunnong.atvris.portal.service.CommentsService;
import site.yunnong.atvris.portal.service.UserManageService;
import site.yunnong.atvris.service.InteractionService;
import site.yunnong.atvris.service.UserInterestTagService;
import site.yunnong.atvris.service.UserProfileService;
import site.yunnong.atvris.service.UserService;
import site.yunnong.atvris.service.helper.BuildHelper;
import site.yunnong.atvris.service.helper.OperatorHelper;
import site.yunnong.atvris.service.vo.UserEducationVO;
import site.yunnong.atvris.service.vo.UserInfoVO;
import site.yunnong.atvris.service.vo.UserInterestTagVO;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;

/**
 * @author zjh
 * @date 2021/7/19 10:12
 */
@Slf4j
@Service
public class UserManageServiceImpl implements UserManageService {

    @Resource
    private UserService userService;
    @Resource
    private UserInterestTagService userInterestTagService;
    @Resource
    private UserProfileService userProfileService;
    @Resource
    private InteractionService interactionService;
    @Resource
    private CommentsService commentsService;
    @Resource
    private UserMapper userMapper;
    @Resource
    private CommentsMapper commentsMapper;
    @Resource
    private NewsMapper newsMapper;
    @Resource
    private ReplyMapper replyMapper;
    @Resource
    private VideoMapper videoMapper;
    @Resource
    private ThreadPoolExecutor selfThreadPoolExecutor;

    @Override
    public UserInfoVO getUserInfo() {
        User user = OperatorHelper.getCurrentUser();
        UserInfoVO vo = new UserInfoVO();
        BeanUtils.copyProperties(user, vo);
        List<UserInterestTagVO> tags = userInterestTagService.getUserInterestTags(user.getUuid());
        vo.setInterestTags(tags);
        UserProfile userProfile = userProfileService.getUserProfileByUuid(user.getUuid());
        BeanUtils.copyProperties(userProfile, vo);
        return vo;
    }

    @Override
    public UserInfoVO queryInfoByUuid(Long uuid) {
        User user = userService.queryByUuid(uuid);
        if (user == null) {
            return null;
        }
        UserProfile userProfile = userProfileService.getUserProfileByUuid(uuid);
        UserInfoVO vo = BuildHelper.buildUserInfoVO(user, userProfile);
        if (OperatorHelper.isLogin()) {
            // 登录状态
            Long loginUuid = OperatorHelper.getLoginUuid();
            vo.setHasFollowed(interactionService.hasFollowed(loginUuid, uuid));
        } else {
            vo.setHasFollowed(false);
        }
        vo.setFansCount((int) interactionService.findUserFansCount(uuid));
        vo.setFollowCount((int) interactionService.findUserFollowCount(uuid));
        vo.setLikedCount(interactionService.findUserLikedCount(uuid));
        vo.setViewCount(interactionService.findUserViewCount(uuid));
        return vo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateAvatar(String fileName) {
        Long uuid = OperatorHelper.getLoginUuid();
        // 哪个表中有关联的avatar信息，则更新
        // 更新user
        User newUser = User.builder().avatar(fileName).build();
        UserExample userExample = new UserExample();
        userExample.createCriteria().andUuidEqualTo(uuid);
        userMapper.updateByExampleSelective(newUser, userExample);
        // 更新comments
        Comments newComment = Comments.builder().userAvatar(fileName).build();
        CommentsExample commentsExample = new CommentsExample();
        commentsExample.createCriteria().andUuidEqualTo(uuid);
        commentsMapper.updateByExampleSelective(newComment, commentsExample);
        // 更新news
        News news = News.builder().userAvatar(fileName).build();
        NewsExample newsExample = new NewsExample();
        newsExample.createCriteria().andUuidEqualTo(uuid);
        newsMapper.updateByExampleSelective(news, newsExample);
        // todo 如果回复表中有avatar信息，也需要更新

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateInfo(UserUpdateParam param) {
        if (param.getNickname() != null && isNicknameUsedByOthers(param.getNickname()) > 0) {
            throw new YunnongBusinessException(ResultCodeEnum.ERROR_PARAM_ILLEGAL, "该昵称已被使用");
        }
        Long uuid = OperatorHelper.getLoginUuid();
        UserExample example = new UserExample();
        example.createCriteria().andUuidEqualTo(uuid);
        User user = buildUser(param);
        userMapper.updateByExampleSelective(user, example);
        if(!OperatorHelper.getCurrentUser().getNickname().equals(param.getNickname())) {
            // nickname修改
            CompletableFuture.runAsync(() -> {
                log.info("修改昵称的处理逻辑...");
                // comments
                Comments comments = new Comments();
                comments.setUserNickname(user.getNickname());
                CommentsExample commentsExample = new CommentsExample();
                commentsExample.createCriteria().andUuidEqualTo(uuid);
                commentsService.updateByExampleSelective(comments, commentsExample);
                // news
                News news = new News();
                news.setUserNickname(user.getNickname());
                NewsExample newsExample = new NewsExample();
                newsExample.createCriteria().andUuidEqualTo(uuid);
                newsMapper.updateByExampleSelective(news, newsExample);
                // reply
                Reply reply = new Reply();
                reply.setUserNickname(user.getNickname());
                ReplyExample replyExample = new ReplyExample();
                replyExample.createCriteria().andUuidEqualTo(uuid);
                replyMapper.updateByExampleSelective(reply, replyExample);
                Reply reply1 = new Reply();
                reply1.setToUserNickname(user.getNickname());
                ReplyExample replyExample1 = new ReplyExample();
                replyExample1.createCriteria().andToUuidEqualTo(uuid);
                replyMapper.updateByExampleSelective(reply1, replyExample1);
                // video
                Video video = new Video();
                video.setUserNickname(user.getNickname());
                VideoExample videoExample = new VideoExample();
                videoExample.createCriteria().andUuidEqualTo(uuid);
                videoMapper.updateByExampleSelective(video, videoExample);
                log.info("修改昵称的处理逻辑完成");
            }, selfThreadPoolExecutor).exceptionally(throwable -> {
                log.error("修改昵称发生错误，message:{}", throwable.getMessage());
                throw new YunnongBusinessException(ResultCodeEnum.ERROR_BUSINESS, throwable);
            });
        }
    }

    @Override
    public int isNicknameUsedByOthers(String nickname) {
        Long uuid = OperatorHelper.getLoginUuid();
        UserExample example = new UserExample();
        example.createCriteria()
                .andNicknameEqualTo(nickname)
                .andUuidNotIn(Collections.singletonList(uuid));
        List<User> users = userMapper.selectByExample(example);
        if (CollectionUtils.isNotEmpty(users)) {
            // 表明已有其他用户使用该昵称
            return 1;
        }
        return 0;
    }

    @Override
    public List<UserEducationVO> queryEducationEnumList() {
        return Arrays.stream(UserEducationEnum.values()).map(this::buildUserEducationVO).collect(Collectors.toList());
    }

    private UserEducationVO buildUserEducationVO(UserEducationEnum educationEnum) {
        return UserEducationVO.builder()
                .value(educationEnum.getValue())
                .name(educationEnum.getName())
                .build();
    }

    private User buildUser(UserUpdateParam param) {
        User user = User.builder().build();
        if (StringUtils.isNotBlank(param.getNickname())) {
            user.setNickname(param.getNickname());
        }
        if (param.getGender() != null) {
            user.setGender(param.getGender());
        }
        if (StringUtils.isNotBlank(param.getJob())) {
            user.setJob(param.getJob());
        }
        if (StringUtils.isNotBlank(param.getPersonalSign())) {
            user.setPersonalSign(param.getPersonalSign());
        }
        if (param.getAge() != null) {
            user.setAge(param.getAge());
        }
        if (param.getEducation() != null) {
            user.setEducation(param.getEducation());
        }
        if (StringUtils.isNotBlank(param.getProvince())) {
            user.setProvince(param.getProvince());
        }
        if (StringUtils.isNotBlank(param.getCity())) {
            user.setCity(param.getCity());
        }
        if (StringUtils.isNotBlank(param.getDistrict())) {
            user.setDistrict(param.getDistrict());
        }
        return user;
    }
}
